package typejump.objects;

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Composite;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;

import typejump.Settings;

/**
 * Represents an animated text effect, which is
 * used for making TextCommands appear more awesome and stuff.
 * @author g
 *
 */
public class TextEffect extends GameObject {

	private String text;
	private Font font;
	private FontMetrics fm;
	private Color color;
	private double duration = Settings.getDouble("texteffect.duration");
	private double time = 0;
	
	private boolean timeless = false;
	
	private static final Composite[] ALPHAS = generateComposites();
	
	private static final Composite[] generateComposites() {
		Composite[] cs = new Composite[10];
		for (int i = 0; i < cs.length; i++) {
			float alpha = ((cs.length-i)/(float)cs.length);
			cs[i] = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha);
		}
		return cs;
	}

	/**
	 * Creates a new TextEffect
	 * @param text - the text to be displayed
	 * @param x - the starting x-coordinate (center)
	 * @param y - the starting y-coordinate (bottom)
	 * @param vx - the x-velocity
	 * @param vy - the y-velocity
	 * @param color - the font color
	 * @param font - the font
	 */
	public TextEffect(String text, double x, double y, double vx, double vy, Color color, Font font) {
		centerX(x);
		centerY(y);
		vx(vx);
		vy(vy);
		this.color = color;
		this.font = font;
		this.text = text;
	}

	/**
	 * Creates a new TextEffect with the default font
	 * @param text - the text to be displayed
	 * @param x - the starting x-coordinate (center)
	 * @param y - the starting y-coordinate (bottom)
	 * @param vx - the x-velocity
	 * @param vy - the y-velocity
	 * @param color - the font color
	 */
	public TextEffect(String text, double x, double y, double vx, double vy, Color color) {
		this(text, x, y, vx, vy, color, new Font("sans-serif", Font.BOLD, 16));
	}
	/**
	 * Creates a new TextEffect with the default font and no velocity
	 * @param text - the text to be displayed
	 * @param x - the starting x-coordinate (center)
	 * @param y - the starting y-coordinate (bottom)
	 * @param color - the font color
	 */
	public TextEffect(String text, double x, double y, Color color) {
		this(text, x, y, 0, 0, color, new Font("sans-serif", Font.BOLD, 16));
	}
	/**
	 * Creates a new TextEffect with the default color and no velocity
	 * @param text - the text to be displayed
	 * @param x - the starting x-coordinate (center)
	 * @param y - the starting y-coordinate (bottom)
	 * @param font - the font
	 */
	public TextEffect(String text, double x, double y, Font font) {
		this(text, x, y, 0, 0, Color.BLACK, font);
	}

	/**
	 * Creates a new TextEffect with the default font and color
	 * @param text - the text to be displayed
	 * @param x - the starting x-coordinate (center)
	 * @param y - the starting y-coordinate (bottom)
	 * @param vx - the x-velocity
	 * @param vy - the y-velocity
	 */
	public TextEffect(String text, double x, double y, double vx, double vy) {
		this(text, x, y, vx, vy, Color.BLACK);
	}

	/**
	 * Creates a new TextEffect with the default font and color and no velocity
	 * @param text - the text to be displayed
	 * @param x - the starting x-coordinate (center)
	 * @param y - the starting y-coordinate (bottom)
	 */
	public TextEffect(String text, double x, double y) {
		this(text, x, y, 0, 0);
	}
	
	/**
	 * Creates a new text effect that pulls its color, font, velocity, and duration
	 * from Settings using the specified prefix.
	 * @param prefix - the setting prefix (eg, "dev" for "texteffect.dev")
	 * @param text - the text to be displayed
	 * @param x - the starting x-center
	 * @param y - the starting baseline
	 * @return
	 */
	public static TextEffect createFromSettings(String prefix, String text, double x, double y) {
		TextEffect te = new TextEffect(text, x, y);
		te.vx(Settings.getDouble(prefix + ".vx"));
		te.vy(Settings.getDouble(prefix + ".vy"));
		te.setColor(new Color(Settings.getInt(prefix + ".color")));
		int fsize = Settings.getInt(prefix + ".size");
		if (fsize == 0) fsize = 16;
		te.setFont(new Font("sans-serif", Font.BOLD, fsize));
		double dur = Settings.getDouble(prefix + ".time");
		if (dur == 0) dur = Settings.getDouble("texteffect.duration");
		te.setDuration(dur);
		
		return te;
	}
	
	/**
	 * Sets the fade on this text effect (0-1)
	 * @param d
	 */
	public void setFade(double d) {
		this.time = d * this.duration;
	}
	
	/**
	 * Sets whether the fade on this text effect is controlled by time
	 * (default is yes)
	 * @param b
	 */
	public void setTimeless(boolean b) {
		this.timeless = b;
	}
	
	/**
	 * Sets the time this TextEffect will take to fade in seconds
	 * @param d
	 */
	public void setDuration(double d) {
		this.duration = d;
	}
	
	/**
	 * Sets the text this TextEffect will display
	 * @param text
	 */
	public void setText(String text) {
		this.text = text;
	}
	
	/**
	 * Sets the color of this TextEffect
	 * @param c
	 */
	public void setColor(Color c) {
		this.color = c;
	}
	
	/**
	 * Sets the Font of this TextEffect
	 * @param f
	 */
	public void setFont(Font f) {
		this.font = f;
		this.fm = null;
	}
	
	private int getCompositeIndex() {
		int i = (int)( ALPHAS.length * time / duration );
		if (i >= ALPHAS.length) i = ALPHAS.length-1;
		return i;
	}
	
	private Composite getComposite() {
		return ALPHAS[getCompositeIndex()];
	}
	
	@Override
	public boolean paintEnabled() {
		return true;
	}
	
	private int offx = 0;
	private int offy = 0;

	@Override
	public void paint(Graphics2D g) {
		g.setColor(color);
		Composite c = g.getComposite();
		g.setComposite(getComposite());
		g.setFont(font);
		if (fm == null) {
			fm = g.getFontMetrics();
			
			offx = -fm.stringWidth(text)/2;
			offy = fm.getAscent() - fm.getHeight()/2;
		}

		g.drawString(text, offx, offy);
		
		g.setComposite(c);
	}

	@Override
	public void update(double time) {
		if (!timeless)
			this.time += time;
		if (this.time > this.duration) {
			remove();
		} else {
			updatePosition(time);
		}
	}

}
